import { Injectable, NestMiddleware, UnauthorizedException, BadRequestException, HttpStatus, HttpException } from '@nestjs/common'
import { Request, Response, NextFunction } from 'express'
import { JwtService, TokenExpiredError, JsonWebTokenError } from '@nestjs/jwt'
import { RedisService } from 'src/redis/redis.service'
import { AuthService } from 'src/auth/auth.service'

@Injectable()
export class AuthMiddlewareMiddleware implements NestMiddleware {
  constructor(
    private readonly jwtService: JwtService,
    private readonly redisService: RedisService,
    private readonly authService: AuthService
  ) { }

  async use(req: Request, res: Response, next: NextFunction) {
    let playload
    //需要重新登录的状态码返回401，刷新token返回403
    try {
      const authorizationHeader = req.headers.authorization
      if (!authorizationHeader) throw new UnauthorizedException('Authorization header not found')
      const [bearer, accessToken] = authorizationHeader.split(' ')
      if (bearer !== 'Bearer') throw new UnauthorizedException('Invalid authorization type')
      playload = this.jwtService.verify(accessToken)
      let state = await this.redisService.get(`user:${playload.id}`)
      if (state != null && state != undefined && +state == 0) throw new HttpException('您已被封禁', HttpStatus.UNAUTHORIZED)
      next()
    } catch (error) {
      //过期和报错都要重新登录，有refreshToken会刷新token
      if (error instanceof TokenExpiredError) {
        //可以通过refreshtoken 重新刷新token
        console.log('token 中间件报错：Access token has expired--token过期,使用refreshtoken')
        // 检查Refresh Token是否存在且未被替换
        if (!req.headers['x-refresh-token']) {
          //过期了也没有refreshToken //需要重新登录了
          throw new UnauthorizedException('token_expired')
        } else {
          try {
            let getRefreshToken = req.headers['x-refresh-token'] as string
            let playload2 = this.jwtService.verify(getRefreshToken)
            const refreshToken = await this.redisService.get(`user:${playload2.id}:refreshToken`)
            if (!refreshToken || refreshToken !== getRefreshToken) {
              throw new UnauthorizedException('access_token_expired  And Refresh token is invalid or has been refreshed')
            } else {
              //通过Refresh Token生成新的Access Token并返回给客户端
              let data = (await this.redisService.getHashData(`user:${playload2.id}:userInfo`, 'all')) as Record<string, string>
              let result = await this.authService.login(data, 'replay')
              console.log(result, 'result')
              res.status(HttpStatus.FORBIDDEN).send({ message: 'token_refresh', result, code: 403 })
            }
          } catch (err) {
            if (err instanceof TokenExpiredError) throw new UnauthorizedException('refeshtoken_expired')
            if (err instanceof JsonWebTokenError) throw new UnauthorizedException('refeshtoken_error')
            throw new UnauthorizedException(err.message)
          }
        }
      } else if (error instanceof JsonWebTokenError) {
        //需要重新登录
        console.log('token 中间件报错：Invalid or malformed JWT token--token错误')
        res.status(HttpStatus.UNAUTHORIZED).json({ message: 'token_error', code: -1, data: {} })
      } else {
        console.log('token 中间件发生未知错误')
        res.status(HttpStatus.UNAUTHORIZED).send({ message: error.message, code: -1, data: {} })
      }
    }
  }
}
